4.5 Навигация между экранами
3 из 3 шагов пройдено

 Навигация между экранами

➡️Ссылка на репозиторий с кодом этого урока

Таблица маршрутизации

При большом количестве экранов используется таблица маршрутизации.

С помощью таблицы маршрутизации устанавливается соответствие между именами маршрутов и виджетами экранов.

Указывается таблица внутри виджета MaterialApp в параметр routes

 

Файл main.dart

import 'package:flutter/material.dart';

import 'screens/main_screen.dart';
import 'screens/first_screen.dart';
import 'screens/second_screen.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Навигация в Flutter',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      initialRoute: '/main', // Этот экран запустится первым
      routes: {
        '/main': (context) => MainScreen(),
        '/first': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}
  • initialRoute: '/main' теперь вместо home: const MainScreen()
  • initialRoute это начальный экран
  • Navigator.pushNamed() более простой и красивый метод для перехода на другой экран

Например, чтобы теперь перейти с экрана MainScreen на экран FirstScreen в обработчике нажатия на кнопку пишем этот код:

ElevatedButton(
  onPressed: () => Navigator.pushNamed(context, '/first'),
  child: const Text("Открыть FirstScreen"),
),

Файл main_screen.dart

import 'package:flutter/material.dart';

class MainScreen extends StatelessWidget {
  const MainScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Главный экран'), centerTitle: true),
      backgroundColor: Colors.white,
      body: SizedBox(
        width: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pushNamed(context, '/first'),
              child: const Text("Открыть FirstScreen"),
            ),
          ],
        ),
      ),
    );
  }
}

Файл first_screen.dart

import 'package:flutter/material.dart';

class FirstScreen extends StatelessWidget {
  const FirstScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Первый экран'),
        backgroundColor: Colors.green[300],
      ),
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            colors: [Color(0xFFBFF098), Color(0xFF6FD6FF)],
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
          ),
        ),
        child: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, '/second'),
                child: const Text("Открыть 2й экран"),
              ),
              ElevatedButton(
                onPressed: () => Navigator.pop(context),
                child: const Text("Вернуться Назад"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Наименование роутов

В данной таблице названия роутов прописаны вручную /main /first /second


routes: {
  '/main': (context) => MainScreen(),
  '/first': (context) => FirstScreen(),
  '/second': (context) => SecondScreen(),
},

Когда экранов условно 3-5 такой подход нормальный. Но когда их становится 30-50, можно легко ошибиться, забыть название и сделать другие косяки.

Поэтому рекомендуется указывать имя роута внутри самого класса как static значение

Файл main_screen.dart

class MainScreen extends StatelessWidget {
  static const routeName = '/main'; // Указываем имя экрана
  // ...

Файл first_screen.dart

class FirstScreen extends StatelessWidget {
  static const routeName = '/first'; // Указываем имя экрана
  // ...

Файл second_screen.dart

class SecondScreen extends StatelessWidget {
  static const routeName = '/second'; // Указываем имя экрана
  // ...

Теперь внутри таблицы маршрутизации указываем так

Файл main.dart

import 'package:flutter/material.dart';

import 'screens/main_screen.dart';
import 'screens/first_screen.dart';
import 'screens/second_screen.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Навигация в Flutter',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      initialRoute: MainScreen.routeName,
      routes: {
        MainScreen.routeName: (context) => MainScreen(),
        FirstScreen.routeName: (context) => FirstScreen(),
        SecondScreen.routeName: (context) => SecondScreen(),
      },
    );
  }
}

Обработчики нажатия тоже нужно изменить

Файл main_screen.dart

ElevatedButton(
  onPressed: () => Navigator.pushNamed(context, FirstScreen.routeName),
  child: const Text("Открыть FirstScreen"),
),

Файл first_screen.dart

ElevatedButton(
  onPressed: () => Navigator.pushNamed(context, SecondScreen.routeName),
  child: const Text("Открыть 2й экран"),
),

Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий